/*
 * this header file defines the class ModularStore
 */

#ifndef __CCCC_MOD_STR_H
#define __CCCC_MOD_STR_H
#include <iostream>
#include "cccc_mod_module_tree.h"
#include "cccc_mod_sinfile.h"
#include "cccc_mod_util.h"
#include "cc_html_interface.h"
#include "cccc_mod_sinfile.h"
#include <vector>
#include <sstream>
//#include <string>
//#include "cccc_mod_atom.h"

string MODULE_DEF_VIO = "MODULE DEFINE VIOLATION";
string SUBMODULE_DEF_VIO = "SUBMODULE DEFINE VIOLATION";
string TOO_DEEP_VIO = "TOO DEEP MODULE LEVEL VIOLATION";
string FAN_VIO = "FANOUT VIOLATION";

string NOT_VISIBLE = ": NOT_VISIBLE";
using namespace std;

class ModularStore {
public:
	static ModularStore * getInstance();
	SingleFile * currentFile;
	ModuleTreeNode * getModuleTree() {
		return this->moduleTree;
	}

	void setModuleTreeRoot(ModuleTreeNode * treeRoot) {
		this->moduleTree = treeRoot;
	}

	void ModularCheck();

	void increaseNumFunc();

	void setNumFunc(int numFunc);

	void setRootPath(string rootPath);

	string getRootPath();
	SingleFile *getCurrentFile() const {
		return currentFile;
	}

	int getNUM_COMPONENTS() const {
		return NUM_COMPONENTS;
	}

	int getNUM_FILES() const {
		return NUM_FILES;
	}

	int getNUM_FUNCS() const {
		return NUM_FUNCS;
	}

	double getNUM_FUNCS_PER_COMPONENT() const {
		return NUM_FUNCS_PER_COMPONENT;
	}

	double getNUM_FUNCS_PER_FILE() const {
		return NUM_FUNCS_PER_FILE;
	}

	double getNUM_FUNCS_PER_MODULE() const {
		return NUM_FUNCS_PER_MODULE;
	}

	double getNUM_FUNCS_PER_SUBMODULE() const {
		return NUM_FUNCS_PER_SUBMODULE;
	}

	int getNUM_MODULES() const {
		return NUM_MODULES;
	}

	int getNUM_SUBMODULES() const {
		return NUM_SUBMODULES;
	}

	string getROOT_PATH() const {
		return ROOT_PATH;
	}

	void setNUM_FUNCS(int NUM_FUNCS) {
		this->NUM_FUNCS = NUM_FUNCS;
	}

	void setNUM_FUNCS_PER_COMPONENT(double NUM_FUNCS_PER_COMPONENT) {
		this->NUM_FUNCS_PER_COMPONENT = NUM_FUNCS_PER_COMPONENT;
	}

	void setNUM_FUNCS_PER_FILE(double NUM_FUNCS_PER_FILE) {
		this->NUM_FUNCS_PER_FILE = NUM_FUNCS_PER_FILE;
	}

	void setNUM_FUNCS_PER_MODULE(double NUM_FUNCS_PER_MODULE) {
		this->NUM_FUNCS_PER_MODULE = NUM_FUNCS_PER_MODULE;
	}

	void setNUM_FUNCS_PER_SUBMODULE(double NUM_FUNCS_PER_SUBMODULE) {
		this->NUM_FUNCS_PER_SUBMODULE = NUM_FUNCS_PER_SUBMODULE;
	}

	void adapt_single_file(SingleFile * file, NodeImp* node, string path);
	void build_up_tree(ModularStore * module, NodeImp* node);

	void adapt_mod(ModuleTreeNode * module, NodeImp* node, string path);

	int adapt_next_nest_num(ModuleTreeNode * module);
	int adapt_LOC(ModuleTreeNode * module);

	int adapt_LineOfCode(ModuleTreeNode * module);
	int adapt_LineOfComm(ModuleTreeNode * module);
	int adapt_LineOfSrc(ModuleTreeNode * module);
	int adapt_LineOfSpeIf(ModuleTreeNode * module);

	int adapt_NOFUN(ModuleTreeNode * module);
	int adapt_NOFILE(ModuleTreeNode * module);
	int adapt_NonDefVisHeader(ModuleTreeNode * module);

	void adapt_voilation(SingleFile * atmoc, NodeImp* node, string path);
	void adapt_voilation(ModuleTreeNode * atmoc, NodeImp* node, string path);

	void adapt_fanin(ModularAtomic * atomic, NodeImp* node, string path);
	void adapt_fanin(ModuleTreeNode * atomic, NodeImp* node, string path);

	void adapt_fanout(ModularAtomic * atomic, NodeImp* node, string path);
	void adapt_fanout(ModuleTreeNode * atomic, NodeImp* node, string path);

	void adapt_funcs(SingleFile* file,NodeImp* node,string path);

protected:
	ModularStore() {
		NUM_COMPONENTS = 0;
		NUM_MODULES = 0;
		NUM_SUBMODULES = 0;
		NUM_FILES = 0;
		NUM_FUNCS_PER_COMPONENT = 0;
		NUM_FUNCS_PER_MODULE = 0;
		NUM_FUNCS_PER_SUBMODULE = 0;
		NUM_FUNCS_PER_FILE = 0;
		NUM_FUNCS = 0;
	}

	~ModularStore() {
		delete (this->_instance);
		this->_instance = NULL;
	}

private:
	static ModularStore * _instance;
	ModuleTreeNode * moduleTree;
	int NUM_COMPONENTS;
	int NUM_MODULES;
	int NUM_SUBMODULES;
	int NUM_FILES;
	double NUM_FUNCS_PER_COMPONENT;
	double NUM_FUNCS_PER_MODULE;
	double NUM_FUNCS_PER_SUBMODULE;
	double NUM_FUNCS_PER_FILE;
	int NUM_FUNCS;
	string ROOT_PATH;

	void check(ModuleTreeNode * node);
};

ModularStore * ModularStore::_instance = NULL;

ModularStore * ModularStore::getInstance() {
//	cout << "modular store" << endl;
	(_instance == NULL) ? _instance = new ModularStore() : 0; //lazy initialization
	return _instance;
}

void ModularStore::setRootPath(string rootPath) {
	this->ROOT_PATH = rootPath;
}

string ModularStore::getRootPath() {
	return this->ROOT_PATH;
}

void ModularStore::ModularCheck() {
	//cout << moduleTree->files.size() << endl;
	//cout << moduleTree->files[0] << endl;
	//cout << moduleTree->files[0]->getFilename() << endl;

	//	cout << "### Enter ModularCheck " << endl;

	check(this->moduleTree);

	//	cout << "NUM_FILES " << this->NUM_FILES << endl;
	//	cout << "NUM_COMPONENTS " << this->NUM_COMPONENTS << endl;
	//	cout << "NUM_MODULES " << this->NUM_MODULES << endl;
	//	cout << "NUM_SUBMODULES " << this->NUM_SUBMODULES << endl;
	//	cout << "NUM_FUNCS" << this->NUM_FUNCS << endl;

	//	this->NUM_FUNCS_PER_COMPONENT = (double) (this->NUM_FUNCS)
	//			/ (this->NUM_COMPONENTS);
	//	this->NUM_FUNCS_PER_FILE = (double) (this->NUM_FUNCS) / (this->NUM_FILES);
	//	this->NUM_FUNCS_PER_MODULE = (double) (this->NUM_FUNCS)
	//			/ (this->NUM_MODULES);
	//	this->NUM_FUNCS_PER_SUBMODULE = (double) (this->NUM_FUNCS)
	//			/ (this->NUM_SUBMODULES);

	//	cout << "NUM_FUNCS_PER_COMPONENT " << this->NUM_FUNCS_PER_COMPONENT << endl;
	//	cout << "NUM_FUNCS_PER_FILE " << this->NUM_FUNCS_PER_FILE << endl;
	//	cout << "NUM_FUNCS_PER_MODULE " << this->NUM_FUNCS_PER_MODULE << endl;
	//	cout << "NUM_FUNCS_PER_SUBMODULE " << this->NUM_FUNCS_PER_SUBMODULE << endl;
	//	cout << "######### ROOT:" << this->ROOT_PATH << endl;

	//	cout << "### ModularCheck Okay" << endl;
}

string mod_line = "";
string submod_line = "";
stringstream ss;
vector<AViolation *> * checkRootLevel(SingleFile * file) {
	vector<AViolation *> *vio = new vector<AViolation *> ();
	int i;
	if (file->getMODULE() != "NO_DEFINE") {
		vio->push_back(new AViolation(MODULE_DEF_VIO, file->getFilename(),
				file->getMODULE_DEF_LINE(), 1));
	}
	if (file->getSUBMODULE() != "NO_DEFINE") {
		vio->push_back(new AViolation(SUBMODULE_DEF_VIO, file->getFilename(),
				file->getSUBMODULE_DEF_LINE(), 1));
	}
	for (i = 0; i < vio->size(); i++) {
		file->addViolation((*vio)[i]);
	}
	return vio;
}

vector<AViolation *> * checkComponentLevel(SingleFile * file) {
	vector<AViolation *> *vio = new vector<AViolation *> ();
	int i;
	if (file->getMODULE() != "NO_DEFINE")
		vio->push_back(new AViolation(MODULE_DEF_VIO, file->getFilename(),
				file->getMODULE_DEF_LINE(), 1));
	if (file->getSUBMODULE() != "NO_DEFINE")
		vio->push_back(new AViolation(SUBMODULE_DEF_VIO, file->getFilename(),
				file->getSUBMODULE_DEF_LINE(), 1));
	for (i = 0; i < vio->size(); i++) {
		file->addViolation((*vio)[i]);
	}
	return vio;
}

vector<AViolation *> * checkModuleLevel(ModularAtomic * module,
		SingleFile * file) {
	vector<AViolation *> *vio = new vector<AViolation *> ();
	int i;
	if (file->getMODULE() != module->getModuleDef())
		vio->push_back(new AViolation(MODULE_DEF_VIO, file->getFilename(),
				file->getMODULE_DEF_LINE(), 1));
	if (file->getSUBMODULE() != "NO_DEFINE")
		vio->push_back(new AViolation(SUBMODULE_DEF_VIO, file->getFilename(),
				file->getSUBMODULE_DEF_LINE(), 1));
	for (i = 0; i < vio->size(); i++) {
		file->addViolation((*vio)[i]);
	}
	return vio;
}

vector<AViolation *> * checkSubModuleLevel(ModularAtomic * module,
		SingleFile * file) {
	vector<AViolation *> *vio = new vector<AViolation *> ();
	int i;
	if (file->getMODULE() != module->getMODULE())
		vio->push_back(new AViolation(MODULE_DEF_VIO, file->getFilename(),
				file->getMODULE_DEF_LINE(), 1));
	if (file->getSUBMODULE() != module->getSUBMODULE())
		vio->push_back(new AViolation(SUBMODULE_DEF_VIO, file->getFilename(),
				file->getSUBMODULE_DEF_LINE(), 1));
	for (i = 0; i < vio->size(); i++) {
		file->addViolation((*vio)[i]);
	}
	return vio;
}

vector<AViolation *> * checkTooDeepModuleLevel(ModularAtomic * module,
		SingleFile * file) {
	vector<AViolation *> *vio = new vector<AViolation *> ();
	int i;
	vio->push_back(new AViolation(TOO_DEEP_VIO, module->getModuleDef(), 0, 2));
	for (i = 0; i < vio->size(); i++) {
		file->addViolation((*vio)[i]);
	}
	return vio;
}

void ModularStore::increaseNumFunc() {
	this->NUM_FUNCS++;
}

void ModularStore::setNumFunc(int numFunc) {
	this->NUM_FUNCS = numFunc;
}

vector<string> * splitString(string str, string split) {
	vector<string> * ret = new vector<string> ();
	int i;
	int start = 0;
	for (i = 0; i < str.length(); i++) {
		if (str.substr(i, 1) == split) {
			ret->push_back(str.substr(start, i - start));
			start = i + 1;
		}
	}

	ret->push_back(str.substr(start, str.length() - start));
	return ret;
}

std::vector<SingleFile *> * sfvec;
int LC = -1;
ModuleTreeNode * route[4];

SingleFile * getFanout(ModuleTreeNode * node, string path) {

//	cout<<"WTF path start : "<<path<<endl;

	int i;
	int base_level = -1;
	ModuleTreeNode * base_node = node;
	if (node->getModule()->getSteroType() == "ROOT") {
		base_level = 0;
	} else if (node->getModule()->getSteroType() == "COMPONENT") {
		base_level = 1;
	} else if (node->getModule()->getSteroType() == "MODULE") {
		base_level = 2;
	} else if (node->getModule()->getSteroType() == "SUBMODULE") {
		base_level = 3;
	}

	base_node = route[base_level];

//	cout<<"WTF base_node name  : "<<(base_node->getName())<<endl;

	vector<string> * _path = splitString(path, "/");
	for (i = 0; i < _path->size(); i++) {

		if (base_level < 0 || base_level > 3) {
//			cout << "error include:" << path << endl;
			return NULL;
		}
		if ((*_path)[i] == "..") {
			base_level--;
			base_node = route[base_level];
//			cout<<"WTF base_node name .. : "<<(base_node->getName())<<endl;
		} else {
			if (i == _path->size() - 1) {
//				cout << "get file by name : " <<base_node->getName()<< endl;
				return base_node->getFileByName((*_path)[i]);
			} else {
				base_level++;

				base_node = base_node->getChildModuleByName((*_path)[i]);
				if (base_node != NULL) {
//					cout<<"I changed route["<<base_level<<"] to"<<base_node->getName()<<endl;
//					route[base_level] = base_node;
				} else {
//					cout<<"WTF path Error : "<<path<<endl;
					return NULL;
				}
			}
		}
	}

}

void ModularStore::check(ModuleTreeNode * node) {
	int i;
	LC++;
	int vio_count;
	vector<AViolation *> *violation;
//	cout << "######## Enter check LEVEL " << LC << endl;
//	cout << "######## Node Type: " << node->getModule()->getSteroType() << endl;
//	cout << "######## Node Name: " << node->getModule()->getModuleDef() << endl;

	if (node->getModule()->getSteroType() == "ROOT") {
		route[0] = node;
	} else if (node->getModule()->getSteroType() == "COMPONENT") {
		route[1] = node;
		this->NUM_COMPONENTS++;
	} else if (node->getModule()->getSteroType() == "MODULE") {
		route[2] = node;
		this->NUM_MODULES++;
	} else if (node->getModule()->getSteroType() == "SUBMODULE") {
		route[3] = node;

		this->NUM_SUBMODULES++;
	}


	for (i = 0; i < node->getFiles().size(); i++) {

		ss << node->getFileAt(i)->getMODULE_DEF_LINE();
		mod_line = ss.str();
		ss << node->getFileAt(i)->getSUBMODULE_DEF_LINE();
		submod_line = ss.str();
		((ModularAtomic *) (node->getFileAt(i)))->setRoot(this->ROOT_PATH);
		this->NUM_FILES++;
		this->NUM_FUNCS += node->getFileAt(i)->getNumFunc();
//		cout << "Single file: " << node->getFileAt(i)->getFilename() << endl;
//		cout << "COMPONENT: " << node->getFileAt(i)->getCOMPONENT() << "#";
//		cout << "MODULE: " << node->getFileAt(i)->getMODULE() << "#";
//		cout << "SUBMODULE: " << node->getFileAt(i)->getSUBMODULE() << endl;
		if (node->getModule()->getSteroType() == "ROOT") {
			violation = checkRootLevel(node->getFileAt(i));
			for (vio_count = 0; vio_count < violation->size(); vio_count++) {
				node->getModule()->addViolation((*violation)[vio_count]);
			}
		}

		else if (node->getModule()->getSteroType() == "COMPONENT") {
			violation = checkComponentLevel(node->getFileAt(i));
			for (vio_count = 0; vio_count < violation->size(); vio_count++) {
				node->getModule()->addViolation((*violation)[vio_count]);
			}
		}

		else if (node->getModule()->getSteroType() == "MODULE") {
			violation = checkModuleLevel(node->getModule(), node->getFileAt(i));
			for (vio_count = 0; vio_count < violation->size(); vio_count++) {
				node->getModule()->addViolation((*violation)[vio_count]);
			}
		}

		else if (node->getModule()->getSteroType() == "SUBMODULE") {
			violation = checkSubModuleLevel(node->getModule(), node->getFileAt(
					i));
			for (vio_count = 0; vio_count < violation->size(); vio_count++) {
				node->getModule()->addViolation((*violation)[vio_count]);
			}
		}

		else if (node->getModule()->getSteroType() == "LEVEL_TOO_DEEP_MODULE") {
			violation = checkTooDeepModuleLevel(node->getModule(),
					node->getFileAt(i));
			for (vio_count = 0; vio_count < violation->size(); vio_count++) {
				node->getModule()->addViolation((*violation)[vio_count]);
			}
		}

//		cout << "### Okay Here" << endl;

		int fan_count;
		for (fan_count = 0; fan_count
				< node->getFileAt(i)->getIncludes()->size(); fan_count++) {
			//TODO
			string include = (*(node->getFileAt(i)->getIncludes()))[fan_count];

//			cout << "### Include " << include << endl;

			SingleFile * fanout = getFanout(node,
					(*splitString(include, ","))[0]);

			if (fanout != NULL) {

//				cout << fanout->getModuleDef() << endl;

//				cout << fanout->getFilename() << endl;
			}

			string temp_file_name = node->getFileAt(i)->getFilename();

//			cout << "file name: " << temp_file_name << endl;

			if (fanout != NULL) {
				cout << "fanout :" << fanout->getVISIBILITY() << endl;
			}

			if (fanout != NULL) {
				 if (fanout->getVISIBILITY() == ""
						|| fanout->getVISIBILITY() == "SUBMODULE") {
//					cout << "###enter 1111" << endl;

					if (fanout->getCOMPONENT()
							== node->getFileAt(i)->getCOMPONENT()
							&& fanout->getMODULE()
									== node->getFileAt(i)->getMODULE()
							&& fanout->getSUBMODULE()
									== node->getFileAt(i)->getSUBMODULE()) {
						node->getFileAt(i)->addFanins(fanout);
						fanout->addFanouts(node->getFileAt(i));//
					} else {
//						cout << "### abbbbb" << endl;

						int line = 1;
//						cout << "OK!!" << endl;
						int type = 1;
						AViolation * avio = new AViolation(
								"FANOUT VIOLATION : NOT_VISIBLE",
								temp_file_name, (*(node->getFileAt(i)->getIncldueLineVec()))[fan_count], 1);

						node->getFileAt(i)->addViolation(avio);
//						cout << "okay 12" << endl;
					}

//					cout << "Okay 22" << endl;
				} else if (fanout->getVISIBILITY() == "COMPONENT") {
//					cout << "### enter 23" << endl;
					if (fanout->getCOMPONENT()
							== node->getFileAt(i)->getCOMPONENT()) {
						node->getFileAt(i)->addFanins(fanout);
						fanout->addFanouts(node->getFileAt(i));
					} else {
						node->getFileAt(i)->addViolation(
								new AViolation(
										FAN_VIO + ": NOT_VISIBLE",
										node->getFileAt(i)->getFilename(),
										(*(node->getFileAt(i)->getIncldueLineVec()))[fan_count],
										1));
					}

//					cout << "### okay 233" << endl;
				} else if (fanout->getVISIBILITY() == "MODULE") {
					if (fanout->getMODULE() == node->getFileAt(i)->getMODULE()
							&& fanout->getCOMPONENT()
									== node->getFileAt(i)->getCOMPONENT()) {
						node->getFileAt(i)->addFanins(fanout);
						fanout->addFanouts(node->getFileAt(i));
					} else {
						node->getFileAt(i)->addViolation(
								new AViolation(
										FAN_VIO + ": NOT_VISIBLE",
										node->getFileAt(i)->getFilename(),
										(*(node->getFileAt(i)->getIncldueLineVec()))[fan_count],
										1));
					}
				} else if (fanout->getVISIBILITY() == ("PUBLIC")) {
					node->getFileAt(i)->addFanins(fanout);
					fanout->addFanouts(node->getFileAt(i));
				}
			} else // fanout=null
			{
//				cout << "J WORRY 3 : "
//						<< (node->getFileAt(i)->getIncldueLineVec()->size())
//						<< endl;
				//			cout<< "J WORRY 2 : "<<(node->getFileAt(i)->getin)<<endl;
				node->getFileAt(i)->addViolation(
						new AViolation(
								FAN_VIO + ": NOT_VISIBLE_NULL_FANOUT",
								node->getFileAt(i)->getFilename(),
								(*(node->getFileAt(i)->getIncldueLineVec()))[fan_count],
								1));
				cout << "find fanout fail : " << include << endl;
			}
		}

		//		cout << "### Okay 2 Here" << endl;

		node->getFileAt(i)->printViolation();
		//		cout << "name : " << node->getFileAt(i)->getFilename() << endl;
		//		cout << "comp : " << node->getFileAt(i)->getCOMPONENT() << endl;
		//		cout << "mod : " << node->getFileAt(i)->getMODULE() << endl;
		//		cout << "submod : "
		//				<< ((ModularAtomic *) (node->getFileAt(i)))->getSUBMODULE()
		//				<< endl;
		//		cout << "repath : "
		//				<< ((ModularAtomic *) (node->getFileAt(i)))->getRelativePath()
		//				<< endl;
	}
	if (LC < 3)
		for (i = 0; i < node->getChildren().size(); i++) {
			//			cout << "modrepath : "
			//					<< ((ModuleTreeNode*) (node->getChildren()[i]))->getModule()->getRelativePath()
			//					<< endl;
			//			cout << "Children module:" << node->getChildren()[i]->getName()
			//					<< endl;
			//			cout << "Children type:"<<node->getChildren()[i]->getType()<<endl;
			check((ModuleTreeNode *) (node->getChildren()[i]));

		}
	LC--;
//	cout << "leave module" << node->getName() << endl;
	return;
}

// TODO

void ModularStore::build_up_tree(ModularStore * module, NodeImp* node) {
	cout << "###Now build up tree " << endl;
	node->setName("report_summary");
	node->setType(ntProj);
	node->setNOF(getNUM_FILES());
	node->setNOC(getNUM_COMPONENTS());
	node->setNOFA(getNUM_FUNCS());
	node->setNOM(getNUM_MODULES());
	node->setNOSM(getNUM_SUBMODULES());

	ModuleTreeNode * module_node = getModuleTree();

	for (int i = 0; i < module_node->getChildren().size(); i++) {
		NodeImp * child = new NodeImp("");
		node->addChild(child);

		adapt_mod(((ModuleTreeNode *) module_node->getChildren()[i]), child, "");

		if (child->get_name() == "SHARE" || child->get_name() == "share"
				|| child->get_name() == "Share") {
			node->setLOC_R(child->getLineOfCode());
			node->setSharedLineOfCode(child->getLineOfCode());
			node->setShardNumOfSpeIf(child->getNumOfSpeIf());
		}
	}

	vector<SingleFile *> files = module_node->getFiles();

	for (int i = 0; i < files.size(); i++) {
		NodeImp * child = new NodeImp("");
		node->addChild(child);

		adapt_single_file(files[i], child, "");
	}

	adapt_voilation(module->getModuleTree(), node, "");

	node->setLOC(this->adapt_LOC(module->getModuleTree()));

	node->setLineOfCode(this->adapt_LineOfCode(module->getModuleTree()));
	node->setLineOfComm(this->adapt_LineOfComm(module->getModuleTree()));
	node->setLineOfSrc(this->adapt_LineOfSrc(module->getModuleTree()));
	node->setNumOfSpeIf(this->adapt_LineOfSpeIf(module->getModuleTree()));
	node->setNONDVH(this->adapt_NonDefVisHeader(module->getModuleTree()));

	node->setLOC_T(node->get_LOC());
}

void ModularStore::adapt_mod(ModuleTreeNode * module, NodeImp* node,
		string path) {
	string current_path = path + module->getModule()->getModuleDef() + "/";

	node->setPath(current_path);
	node->setName(module->getModule()->getModuleDef());
	node->setLOC(this->adapt_LOC(module));

	node->setLineOfCode(this->adapt_LineOfCode(module));
	node->setLineOfComm(this->adapt_LineOfComm(module));
	node->setLineOfSrc(this->adapt_LineOfSrc(module));
	node->setNumOfSpeIf(this->adapt_LineOfSpeIf(module));
	node->setNONDVH(this->adapt_NonDefVisHeader(module));

	node->setNOFA(this->adapt_NOFUN(module));
	node->setNOF(this->adapt_NOFILE(module));

	if (module->getModule()->getSteroType() == "COMPONENT") {
		node->setType(ntCom);
		node->setNOM(module->getChildren().size());
		node->setNOSM(this->adapt_next_nest_num(module));
	} else if (module->getModule()->getSteroType() == "MODULE") {
		node->setType(ntMod);
		node->setNOSM(module->getChildren().size());
	} else if (module->getModule()->getSteroType() == "SUBMODULE") {
		node->setType(ntSmod);
	}

	for (int i = 0; i < module->getChildren().size(); i++) {
		NodeImp * child = new NodeImp("");
		node->addChild(child);
		adapt_mod(((ModuleTreeNode *) module->getChildren()[i]), child,
				current_path);
	}

	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++) {
		NodeImp * child = new NodeImp("");
		node->addChild(child);

		adapt_single_file(files[i], child, current_path);
	}

	node->setPROJECT_R((float) node->get_LOC_REUSABLE() / node->get_LOC_TOTAL());

	adapt_fanin(module, node, current_path);
	adapt_fanout(module, node, current_path);
	adapt_voilation(module, node, current_path);
}

string get_file_name(string src) {
	string retstr = "";

	for (int i = src.length() - 1; i > 0; i--) {
		char temp = src.at(i);

		if (temp == '/') {
			retstr = src.substr(i + 1, src.length());
			break;
		}
	}
	return retstr;
}

int ModularStore::adapt_next_nest_num(ModuleTreeNode * module) {
	int num = 0;

	for (int i = 0; i < module->getChildren().size(); i++)
		num = module->getChildren().at(i)->getChildren().size();

	return num;
}

void ModularStore::adapt_single_file(SingleFile * file, NodeImp* node,
		string path) {
	node->setPath(path);
	node->setName(get_file_name(file->getFilename()));

	node->setType(ntFile);
	node->setLOC(file->getLOC());

	node->setLineOfCode(file->getCodeLineNum());
	node->setLineOfComm(file->getCommLineNum());
	node->setLineOfSrc(file->getCodeLineNum() + file->getCommLineNum());
	node->setNumOfSpeIf(file->getSpeIfdefNum());

	file->getMODULE();
	node->setNOFA(file->getNumFunc());
	node->setAbs_path(file->getFilename());

	adapt_fanin(file, node, path);
	adapt_fanout(file, node, path);
	adapt_voilation(file, node, path);

	adapt_funcs(file,node,path);
}

void ModularStore::adapt_funcs(SingleFile* file,NodeImp* node,string path){
	vector<Func>* funcs = file->getFuncs();

		for (int j = 0; j < funcs->size(); j++) {
//			AViolation * violation = violations->at(j);
			Func * func=&funcs->at(j);

			VoilationImp * v = new VoilationImp("");

			v->set_name(func->getName());
			v->set_line(func->getStartLine());
			v->set_path(path);
			v->setMvg(func->getMvg());

			node->addFuncs(v);
		}
}


// TODO
void ModularStore::adapt_fanin(ModularAtomic * atomic, NodeImp* node,
		string path) {
	vector<ModularAtomic *> * fanin = (atomic->getFanins());

	for (int i = 0; i < fanin->size(); i++) {
		VoilationImp * v = new VoilationImp("");

		v->set_name((*fanin)[i]->getModuleDef());
		v->set_path(path);

		node->addFanin(v);
	}
}

void ModularStore::adapt_fanin(ModuleTreeNode * module, NodeImp* node,
		string path) {
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++) {
		SingleFile * file = files.at(i);

		vector<ModularAtomic *> * fanout = file->getFanins();

		for (int j = 0; j < fanout->size(); j++) {
			ModularAtomic * fan = fanout->at(j);

			VoilationImp * v = new VoilationImp("");

			v->set_name(fan->getModuleDef());
			v->set_path(path);

			node->addFanin(v);
		}
	}

	for (int i = 0; i < module->getChildren().size(); i++)
		adapt_fanin((ModuleTreeNode *) module->getChildren().at(i), node, path);
}

void ModularStore::adapt_fanout(ModularAtomic * atomic, NodeImp* node,
		string path) {
	vector<ModularAtomic *> * fanout = atomic->getFanouts();

	for (int i = 0; i < fanout->size(); i++) {
		VoilationImp * v = new VoilationImp("");

		v->set_name((*fanout)[i]->getModuleDef());
		v->set_path(path);

		node->addFanout(v);
	}
}

void ModularStore::adapt_fanout(ModuleTreeNode * module, NodeImp* node,
		string path) {
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++) {
		SingleFile * file = files.at(i);

		vector<ModularAtomic *> * fanout = file->getFanouts();

		for (int j = 0; j < fanout->size(); j++) {
			ModularAtomic * fan = fanout->at(j);

			VoilationImp * v = new VoilationImp("");

			v->set_name(fan->getModuleDef());
			v->set_path(path);

#ifdef DEBUG
			cout << "# fan path:" << path << endl;
			cout << "# fan 1:"<< fan->getRelativePath() << endl;
#endif
			node->addFanout(v);
		}
	}

	for (int i = 0; i < module->getChildren().size(); i++)
		adapt_fanout((ModuleTreeNode *) module->getChildren().at(i), node, path);
}

void ModularStore::adapt_voilation(SingleFile * atmoc, NodeImp* node,
		string path) {
	vector<AViolation*>* violations = atmoc->getViolation();

	for (int j = 0; j < violations->size(); j++) {
		AViolation * violation = violations->at(j);

		VoilationImp * v = new VoilationImp("");

		v->set_name(violation->getDescription());
		v->set_abs_path(violation->getFile());
		v->set_line(violation->getLine());
		v->set_path(path);

		node->add_violation(v);
	}
}

void ModularStore::adapt_voilation(ModuleTreeNode * module, NodeImp* node,
		string path) {
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++) {
		SingleFile * file = files.at(i);

		vector<AViolation*>* violations = file->getViolation();

		for (int j = 0; j < violations->size(); j++) {
			AViolation * violation = violations->at(j);

			VoilationImp * v = new VoilationImp("");

			v->set_name(violation->getDescription());
			v->set_abs_path(violation->getFile());
			v->set_line(violation->getLine());
			v->set_path(path);

			node->add_violation(v);
		}
	}

	for (int i = 0; i < module->getChildren().size(); i++)
		adapt_voilation((ModuleTreeNode *) module->getChildren().at(i), node,
				path);
}

int ModularStore::adapt_LOC(ModuleTreeNode * module) {
	int local_sum = 0;
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++)
		local_sum += files.at(i)->getLOC();

	for (int i = 0; i < module->getChildren().size(); i++)
		local_sum += adapt_LOC(
				((ModuleTreeNode*) (module->getChildren().at(i))));

	return local_sum;
}

int ModularStore::adapt_LineOfCode(ModuleTreeNode * module) {
	int local_sum = 0;
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++)
		local_sum += files.at(i)->getCodeLineNum();
	for (int i = 0; i < module->getChildren().size(); i++)
		local_sum += adapt_LineOfCode(
				(ModuleTreeNode*) (module->getChildren().at(i)));
	return local_sum;
}

int ModularStore::adapt_LineOfComm(ModuleTreeNode * module) {
	int local_sum = 0;
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++)
		local_sum += files.at(i)->getCommLineNum();
	for (int i = 0; i < module->getChildren().size(); i++)
		local_sum += adapt_LineOfComm(
				(ModuleTreeNode*) (module->getChildren().at(i)));
	return local_sum;
}
int ModularStore::adapt_LineOfSrc(ModuleTreeNode * module) {
	int local_sum = 0;
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++)
		local_sum += (files.at(i)->getCommLineNum()
				+ files.at(i)->getCodeLineNum());
	for (int i = 0; i < module->getChildren().size(); i++)
		local_sum += adapt_LineOfSrc(
				(ModuleTreeNode*) (module->getChildren().at(i)));
	return local_sum;
}
int ModularStore::adapt_LineOfSpeIf(ModuleTreeNode * module) {
	int local_sum = 0;
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++)
		local_sum += (files.at(i)->getSpeIfdefNum());
	for (int i = 0; i < module->getChildren().size(); i++)
		local_sum += adapt_LineOfSpeIf(
				(ModuleTreeNode*) (module->getChildren().at(i)));
	return local_sum;
}
int ModularStore::adapt_NonDefVisHeader(ModuleTreeNode * module) {
	int local_sum = 0;
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++) {
		//			local_sum+=(files.at(i)->getSpeIfdefNum());
		if (files.at(i)->getIsNoneDefault()) {
			local_sum++;
		}
	}
	for (int i = 0; i < module->getChildren().size(); i++)
		local_sum += adapt_NonDefVisHeader(
				(ModuleTreeNode*) (module->getChildren().at(i)));
	return local_sum;
}

int ModularStore::adapt_NOFUN(ModuleTreeNode * module) {
	int local_sum = 0;
	vector<SingleFile *> files = module->getFiles();

	for (int i = 0; i < files.size(); i++)
		local_sum += files.at(i)->getNumFunc();

	for (int i = 0; i < module->getChildren().size(); i++)
		local_sum += adapt_NOFUN(
				((ModuleTreeNode*) (module->getChildren().at(i))));

	return local_sum;
}

int ModularStore::adapt_NOFILE(ModuleTreeNode * module) {
	int local_sum = 0;

	local_sum += module->getFiles().size();

	for (int i = 0; i < module->getChildren().size(); i++)
		local_sum += adapt_NOFILE(((ModuleTreeNode*) (module->getChildren().at(
				i))));

	return local_sum;
}

#endif
